﻿using System;
using System.Windows.Forms;
using Controller;
using NN = NNCore;

namespace Reversi
{
	public partial class UCGame : UserControl
	{
		private ReversiController reversi;
		private Index[] fieldsToHighlight = new Index[0];
		private Index fieldLastSet;

		public bool IsRunning
		{
			get { return reversi.IsRunning; }
		}

        public UCGame(PlayerTypes p1, PlayerTypes p2, NN.Controller nnController1, NN.Controller nnController2, int timerInterval)
		{
			InitializeComponent();
			this.reversi = new ReversiController(p1, p2, nnController1, nnController2);
        
            reversi.TokenPlaced += new ReversiController.TokenPlacedEventHandler(reversi_TokenPlaced);
            reversi.StatusChanged += new ReversiController.StatusChangedEventHandler(reversi_StatusChanged);
            reversi.TimerInterval = timerInterval;
		}

        #region Events

        private void reversi_TokenPlaced(object sender, TokenPlacedEventArgs e)
		{
			RemoveHighlighting();
			this.fieldLastSet = e.Index;
			PaintAllTokens(e.Board);
		}

		private delegate void SetLabelTextsCallback(string status, string player);

		private void reversi_StatusChanged(object sender, StatusChangedEventArgs e)
		{
			SetLabelTexts(e.Status, e.Player);
		}



		private void SetLabelTexts(string status, string player)
		{
			if (this.lblPlayer.InvokeRequired || this.lblStatus.InvokeRequired)
			{
				SetLabelTextsCallback d = new SetLabelTextsCallback(SetLabelTexts);
				this.Invoke(d, status, player);
			}
			else
			{
				lblStatus.Text = string.Format("Status: {0}", status);
				lblPlayer.Text = string.Format("{0}", player);
			}

		}

		private void UCGame_Load(object sender, EventArgs e)
		{
            for (int i = 0; i < this.tableLayoutPanel1.Controls.Count; i++ )
            {
                this.tableLayoutPanel1.Controls[i].Dispose();
            }

			for (int i = 0; i < 8; i++)
			{
				for (int j = 0; j < 8; j++)
				{                  
                    this.tableLayoutPanel1.Controls.Add(new UCField(i, j), i, j);
                    ((UCField)this.tableLayoutPanel1.GetControlFromPosition(i, j)).FieldClicked
                        += new UCField.FieldClickedEventHandler(UCGame_FieldClicked);
				}
			}
			reversi.StartGame();
		}

		private void UCGame_FieldClicked(object sender, FieldClickedEventArgs e)
		{

			reversi.PlaceToken(e.Column, e.Row, typeof(PlayerHuman));
		}

		#endregion

		#region Work

		public void ShowPossibleMoves()
		{
			fieldsToHighlight = reversi.PossibleMoves;
			HighlightFields();
		}

		private void HighlightFields()
		{
			for (int i = 0; i < this.fieldsToHighlight.Length; i++)
			{
				((UCField)tableLayoutPanel1.GetControlFromPosition(fieldsToHighlight[i].Column, fieldsToHighlight[i].Row)).FieldStatus = FieldStatus.Highlighted;
			}
		}

		private void RemoveHighlighting()
		{
			if (fieldLastSet != null)
			{
				((UCField)tableLayoutPanel1.GetControlFromPosition(fieldLastSet.Column, fieldLastSet.Row)).FieldStatus = FieldStatus.Default;
			}
			for (int i = 0; i < this.fieldsToHighlight.Length; i++)
			{
				((UCField)tableLayoutPanel1.GetControlFromPosition(fieldsToHighlight[i].Column, fieldsToHighlight[i].Row)).FieldStatus = FieldStatus.Default;
			}
		}

		private void PaintAllTokens(Token[,] board)
		{
			// Set Tokens
			for (int i = 0; i < board.GetLength(0); i++)
			{
				for (int j = 0; j < board.GetLength(1); j++)
				{
					((UCField)this.tableLayoutPanel1.GetControlFromPosition(i, j)).Token = board[i, j];
				}
			}
			if (fieldLastSet != null)
			{
				((UCField)tableLayoutPanel1.GetControlFromPosition(fieldLastSet.Column, fieldLastSet.Row)).FieldStatus = FieldStatus.LastSet;
			}
		}

		#endregion
	}
}
